#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Datetime: 2020/8/13 19:07
# @Author  : CHEN Wang
# @Site    :
# @File    : testing_script.py
# @Software: PyCharm

"""
对selection_bactest模块进行测试
"""


import pandas as pd
from quant_researcher.quant.project_tool.db_operator import db_conn
from quant_researcher.quant.factors.factor_analysis.factor_analyser.factor_analyse import FactorAnalyseMachine
from quant_researcher.quant.datasource_fetch.index_api.index_constant import SW_WIND_LIST


CON = db_conn.get_derivative_data_conn()
CON_factor = db_conn.get_tk_factors_conn()
CON_astk = db_conn.get_stock_conn()


if __name__ == "__main__":
    # %% 股票资产
    # period_start = '2014-01-01'
    # period_end = '2020-07-17'
    # indicators = pd.read_sql("select stockcode as code, reportdate as tradedate, "
    #                          "roe,pe,sales_growth, cfo_to_earning "
    #                          "from tk_mfdb_23.stk_comp_key_financials "
    #                          f"where reportdate >= '{period_start}'"
    #                          f"and reportdate <= '{period_end}'"
    #                          "order by reportdate, code", CON)
    # indicators['tradedate'] = pd.to_datetime(indicators['tradedate'])
    # indicators = indicators.drop_duplicates(['code', 'tradedate'])
    # %%指数成分股测试
    # indis = BackTest(asset_type='stock',
    #                  sector_name=['000300'],
    #                  sector_type='index',
    #                  weight_method='市值加权',
    #                  begin_date=period_start,
    #                  end_date=period_end,
    #                  indi_data=indicators,
    #                  indi_direction=[1, 0, 1, 1])
    # result2, candidates = indis.run()
    # # %% 股票概念成分股测试
    # indis = BackTest(asset_type='stock',
    #                  sector_name=['5G概念'],
    #                  sector_type='concept',
    #                  begin_date=period_start,
    #                  end_date=period_end,
    #                  indi_data=indicators, indi_direction=[1,0,1,1])
    # result2, candidates = indis.run()
    # #%% 股票行业成分股测试
    # indis = BackTest(asset_type='stock',
    #                  sector_name=['食品饮料', '纺织服装', '商业贸易', '休闲服务', '家用电器'],
    #                  sector_type='industry',
    #                  begin_date=period_start,
    #                  end_date=period_end,
    #                  indi_data=indicators,
    #                  indi_direction=[1, 0, 1, 1])
    # result2, candidates = indis.run()
    # %% 基金资产
    # 自定义资金池测试
    # period_start = '2018-01-01'
    # bond_fund = pd.read_sql(f"select distinct c.fund_code, i.fund_sname "
    #                             f"from tk_mfdb_23.mf_bd_fndclsinfo as c, tk_mfdb_23.mf_bd_fndinfo as i "
    #                             f"where c.category_code = '3001' "
    #                             f"and c.fund_code = i.fund_code", CON)
    # bond_fund = bond_fund[['定' not in x for x in bond_fund['fund_sname']]]
    # external_fund = pd.read_sql(f"select r.end_date as tradedate, r.fund_code as code, "
    #                             f"r.annual_ret "
    #                             f"from tk_mfdb_23.mf_di_fndriskadjretstats_day as ra, tk_mfdb_23.mf_di_fndretstats_day as r "
    #                             f"where r.period_interval = '7' "
    #                             f"and ra.end_date = r.end_date "
    #                             f"and ra.period_interval = r.period_interval "
    #                             f"and ra.fund_code = r.fund_code "
    #                             f"and r.end_date > '{period_start}'"
    #                             f"and r.fund_code in {tuple(bond_fund.fund_code)} ", CON)
    # external_fund['tradedate'] = pd.to_datetime(external_fund['tradedate'])
    # indis = BackTest(asset_type='fund',
    #                 begin_date='2018-01-01',
    #                 end_date='2020-06-01',
    #                 benchmark='000001',
    #                 indi_data=external_fund,
    #                 indi_direction=[1],
    #                 abnormal_threshold=0.03)
    #
    # result2, candidates = indis.run()
    # %% 行业资产测试
    # external_industry = pd.read_sql("select date as tradedate, left(industry_code,6) as code, factor_value as ROA "
    #                                 "from macro_di_industry_factor "
    #                                 "where factor_name = 'ROA' "
    #                                 f"and date > '{period_start}' "
    #                                 f"and date < '{period_end}' ", CON)
    # external_industry = pd.read_sql("select date as tradedate, left(industry_code,6) as swcode, factor_value as CLOSE "
    #                                 "from macro_di_industry_factor "
    #                                 "where factor_name = 'CLOSE' "
    #                                 f"and date > '{period_start}' "
    #                                 f"and date < '{period_end}' ", CON)
    # close_un = external_industry.set_index(['tradedate','swcode'])['CLOSE'].unstack()
    # mom20 = close_un.ffill().pct_change(20,fill_method='ffill').stack().rename('mom20').reset_index()
    # # 申万一级行业
    # external_sw = mom20[mom20.swcode.isin(SW_LIST)]
    # external_sw['tradedate'] = pd.to_datetime(external_sw['tradedate'])
    # external_sw['tradedate'] = external_sw['tradedate'].astype(str)
    # indis = BackTest(asset_type='industry',
    #                  sector_type='申万一级',
    #                  begin_date=period_start,
    #                  end_date=period_end,
    #                  benchmark='avg',
    #                  indi_data=external_factor,
    #                  indi_direction=[1],
    #                  commission=0,
    #                  rebalance_freq='month',
    #                  abnormal_threshold=0.11,
    #                  top=True)
    # result2, candidates = indis.run()
    #%%
    period_start = '2013-01-01'
    period_end = '2020-08-01'
    industry_factor = pd.read_sql("select * from macro_di_industry_factor "
                                  f"where industry_code in {tuple(SW_WIND_LIST)} "
                                  f"and factor_name in ('ROE_AVG', 'debttoassets') ", CON,
                                  index_col=['date', 'industry_code', 'factor_name'])['factor_value'].unstack()

    roe_chg = industry_factor['ROE_AVG'].unstack().pct_change(90, freq='D').ffill()
    debttoasset_chg = industry_factor['DEBTTOASSETS'].unstack().pct_change(365, freq='D').ffill()
    roe_rank = roe_chg.rank(axis=1)
    debttoasset_rank = debttoasset_chg.rank(axis=1)
    # roe_debt = roe_rank * debttoasset_rank
    # roe_debt = roe_rank * 1
    roe_debt = debttoasset_chg.stack().rename('ROE_DEBT').reset_index()
    roe_debt.columns = ['tradedate', 'swcode', 'ROE_DEBT']
    roe_debt['swcode'] = roe_debt['swcode'].str[:6]
    roe_debt['tradedate'] = roe_debt['tradedate'].dt.strftime('%Y-%m-%d')
    FactorAnalyser = FactorAnalyseMachine(factor_name='ROE_DEBT',  # 分析因子名称
                                          begin_date=period_start,  # 分析开始时间
                                          end_date=period_end,  # 分析结束时间
                                          external_data=True,
                                          asset_type='sw',
                                          factor_data=roe_debt,
                                          direction=[1])  # 因子方向正向为1，负向为-1，
    FactorAnalyser.param_setting(period='monthly',  # 调仓周期
                                 universe='HS300',  # 标的池仅对股票有效，基金和基金经理对应标的暂定为上证综指
                                 benchmark='avg',  # 基准代码，如果输入avg则表示所有资产池的平均值
                                 freq=1,  # 调仓频率
                                 bool_exclude_industry=True,  # 中性化是否剔除行业因子，仅对股票有效
                                 list_exclude_style=[])  # 中性化是否剔除风格因子，仅对股票有效
    FactorAnalyser.initial_data(winsor=True, standard=True, method='IR', window=5, orthogonalize=True)  # 数据初始化

    ICstatsdf, long_short_df, group_return_summary, group_return = FactorAnalyser.longshort_portfolio(
        freq=1, group_num=5, winsor=True, neutral=False, standard=True, abnormal_threshold=0.11)  # 因子多空组合的净值曲线
    # all_IC = FactorAnalyser.timeRangeRankIC(freq='', winsor=False, neutral= False, standard=False, rank=True)
    FactorAnalyser.time_range_ic(freq='', winsor=True, neutral=False, standard=True, rank=True)  # 因子rank IC的时间序列展示
    # 中证800行业
